#include "externals.h"
#include "shapes.h"

void init();
void display();
void reshape(int, int);
void key_press(unsigned char, int, int);
void mouse_motion(int, int);
void mouse_click(int, int, int, int);

float alpha = 0.0f;
float beta = 0.0f;

struct MouseState
{
	int button;
	int state;
	int pos_x;
	int pos_y;
} mouse;

// Функция reshape()
//		w - ширина окна
//		h - высота окна
void reshape(int w, int h)
{
	// Устанавливаем область просмотра на все окно
	glViewport(0, 0, w, h);
	// Определяем объем видимости 
	// 1. Устанавливаем текущую матрицу проекций
	glMatrixMode(GL_PROJECTION);
	// 2. Сбрасываем все ее предыдущие значения
	glLoadIdentity();
	// 3. Задаем объем видимости
	gluPerspective(60, (float)w/h, 1.0f, 50.0f);
}

// Функция key_press()
//		key_code - код нажатой клавиши
//		x - координата мыши по горизонтали
//		y - координата мыши по вертикали
void key_press(unsigned char key_code, int x, int y)
{
	switch(key_code)
	{
	case 27: // Esc key
		{
			// Удаляем текущее окно и выходим из программы
			glutDestroyWindow(glutGetWindow());
			exit(0);
		}
	}
}

void mouse_motion(int x, int y)
{
	int dx = x - mouse.pos_x;
	int dy = y - mouse.pos_y;

	if(mouse.state == GLUT_DOWN)
	{
		if(mouse.button == GLUT_LEFT_BUTTON)
		{
			glutSetCursor(GLUT_CURSOR_CYCLE);
			beta += dx/3.0;
			if(beta < 0) beta -= 360;
			if(beta >= 360)	beta += 360;
			alpha += dy/3.0;
			if(alpha < 0) alpha += 360;
			if(alpha >= 360) alpha -= 360;
			glutPostRedisplay();
		}
	}
	mouse.pos_x = x;
	mouse.pos_y = y;
}

void mouse_click(int button, int state, int x, int y)
{
	mouse.button = button;
	mouse.state = state;
	mouse.pos_x = x;
	mouse.pos_y = y;

	if(mouse.state == GLUT_UP) 
	{
		glutSetCursor(GLUT_CURSOR_INHERIT);
	}
}

// Функция display()
// Здесь собственно и должно происходить рисование
void display()
{   
	int*points[]={4,0,2,2,3,2,1,4,2,4,0,6};
	// Очищаем экран цветом фона
	// Очищаем буфер глубины
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// Устанавливаем текущую матрицу модельно-видовых преобразований
	glMatrixMode(GL_MODELVIEW);
	// Сбрасываем ее значения
	glLoadIdentity();

	// Сдвигаем от точки наблюдения по оси z
	glTranslated(0, 0, -30);
	// Поворачиваем при помощи мыши
	glRotatef(alpha, 1, 0, 0);
	glRotatef(beta, 0, 1, 0);

	// Рисуем разноцветный кубик
	//draw_cube(10.0f);
	//draw_tetr(10.0f);
	//draw_conus(10.0f);
	//draw_cyl(10.0, 5.0, 10);
	draw_elka(*points,20);
	// Даем команду на выполнение всех ранее заданных команд
	glFlush();
	// Меняем местами внеэкранный и экранный буферы
	glutSwapBuffers();
}

// Функция init()
// Установка и инициализации начальных значений
void init()
{
	// Явно устанавливаем цвет фона в черный
	glClearColor(0.0, 0.0, 0.0, 0.0);
	// Рисуем закрашенные полигоны
	glShadeModel(GL_FLAT);
	glPolygonMode(GL_FRONT, GL_LINE);
	//glPolygonMode(GL_FRONT, GL_FILL);	
	glEnable(GL_CULL_FACE);

	// Задаем работу с буфером глубины
	glEnable(GL_DEPTH_TEST);

	mouse.state = GLUT_UP;
	mouse.pos_x = 0;
	mouse.pos_y = 0;
	mouse.button = -1;
}

int main(int argc, char **argv)
{
	// Инициализируем библиотеку Glut
	glutInit(&argc, argv);

	// Задаем параметры для OpenGL
	// Двойная буферизация + Буфер глубины + цвет в формате RGB
	glutInitDisplayMode(GLUT_DOUBLE|GLUT_DEPTH|GLUT_RGB);

	// Определяем размеры 
	glutInitWindowSize(600, 500);
	// и позицию окна
	glutInitWindowPosition(0, 0);
	// Создаем собственно окно и указываем его заголовок
	glutCreateWindow("OpenGL");

	// Вызываем нашу пользовательскую функцию установки и инициализации
	// каких либо начальных значений для программы
	init();

	// Регистрируем функцию display() для обработки сообщения "рисование в окне"
	glutDisplayFunc(display);
	// Регистрируем функцию reshape() для обработки сообщения "изменение размеров окна"
	glutReshapeFunc(reshape);
	// Регистрируем функцию key_press() для обработки нажатия клавиш на клавиатуре
	glutKeyboardFunc(key_press);

	// Регистрируем функции mouse_click() и mouse_motion()
	// для обработки кнопок и движения мыши
	glutMouseFunc(mouse_click);
	glutMotionFunc(mouse_motion);

	// запускаем основной цикл программы
	glutMainLoop();

	return 0;          
}
